#include "PEIncludes.h"

#include "PEAliceSoft.h"

namespace pe
{

	int AliceSoftCheckType(AliceSoftType* a_Target, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// Archive RED
		// ================================

		AliceArchiveRedHeader arch_red;
		if (AliceArchiveRedReadHeader(&arch_red, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_ArchiveRed;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Archive AFA
		// ================================

		AliceArchiveAfaHeader arch_afa;
		if (AliceArchiveAfaReadHeader(&arch_afa, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_ArchiveAfa;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image QNT
		// ================================

		AliceImageQntHeader image_qnt;
		if (AliceImageQntReadHeader(&image_qnt, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_ImageQNT;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image PMS
		// ================================

		AliceImagePmsHeader image_pms;
		if (AliceImagePmsReadHeader(&image_pms, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_ImagePms;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image AJP
		// ================================

		AliceImageAjpHeader image_ajp;
		if (AliceImageAjpReadHeader(&image_ajp, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_ImageAjp;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Model
		// ================================

		AliceModelHeader model;
		if (AliceModelReadHeader(&model, a_Stream) == PE_OK)
		{
			*a_Target = eAliceSoftType_Model;
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		*a_Target = eAliceSoftType_Unknown;

		return -1;
	}

	int AliceSoftOpenArchive(PEArchiveRaw* a_Target, const wchar_t* a_Path)
	{
		PEStream read;
		PEStreamOpen(&read, a_Path, L"rb");

		AliceArchiveRedHeader red_header;
		if (AliceArchiveRedReadHeader(&red_header, &read) == PE_OK)
		{
			AliceArchiveRed red_arch;
			AliceArchiveRedReadData(&red_arch, &red_header, &read);

			AliceArchiveRedToRaw(a_Target, &red_arch);

			PEStreamClose(&read);

			return PE_OK;
		}

		PEStreamSeek(&read, 0, SEEK_SET);

		AliceArchiveAfaHeader afa_header;
		if (AliceArchiveAfaReadHeader(&afa_header, &read) == PE_OK)
		{
			AliceArchiveAfa afa_arch;
			AliceArchiveAfaReadData(&afa_arch, &afa_header, &read);

			AliceArchiveAfaToRaw(a_Target, &afa_arch);

			PEStreamClose(&read);

			return PE_OK;
		}

		PEStreamSeek(&read, 0, SEEK_SET);

		AliceArchiveAldHeader ald_header;
		if (AliceArchiveAldReadHeader(&ald_header, &read) == PE_OK)
		{
			AliceArchiveAld ald_arch;
			AliceArchiveAldReadData(&ald_arch, &ald_header, &read);

			AliceArchiveAldToRaw(a_Target, &ald_arch);

			PEStreamClose(&read);

			return PE_OK;
		}

		PEStreamClose(&read);

		return -1;
	}

	int AliceSoftReadImage(PEImageRaw* a_Target, PEStream* a_File)
	{
		// ================================
		// QNT
		// ================================

		PEStreamSeek(a_File, 0, SEEK_SET);

		AliceImageQntHeader qnt_header;
		if (AliceImageQntReadHeader(&qnt_header, a_File) == PE_OK)
		{
			AliceImageQnt qnt_data;
			AliceImageQntReadData(&qnt_data, &qnt_header, a_File);

			AliceImageQntToRaw(a_Target, &qnt_data);

			AliceImageQntDeleteData(&qnt_data);
			AliceImageQntDeleteHeader(&qnt_header);

			PEStreamClose(a_File);

			return PE_OK;
		}

		// ================================
		// PMS
		// ================================

		PEStreamSeek(a_File, 0, SEEK_SET);

		AliceImagePmsHeader pms_header;
		if (AliceImagePmsReadHeader(&pms_header, a_File) == PE_OK)
		{
			AliceImagePms pms_data;
			AliceImagePmsReadData(&pms_data, &pms_header, a_File);

			AliceImagePmsToRaw(a_Target, &pms_data);

			AliceImagePmsDeleteData(&pms_data);
			AliceImagePmsDeleteHeader(&pms_header);

			PEStreamClose(a_File);

			return PE_OK;
		}

		// ================================
		// AJP
		// ================================

		PEStreamSeek(a_File, 0, SEEK_SET);

		AliceImageAjpHeader ajp_header;
		if (AliceImageAjpReadHeader(&ajp_header, a_File) == PE_OK)
		{
			AliceImageAjp ajp_data;
			AliceImageAjpReadData(&ajp_data, &ajp_header, a_File);

			AliceImageAjpToRaw(a_Target, &ajp_data);

			AliceImageAjpDeleteData(&ajp_data);
			AliceImageAjpDeleteHeader(&ajp_header);

			PEStreamClose(a_File);

			return PE_OK;
		}

		PEStreamClose(a_File);

		return -1;
	}

};